import type { AxiosResponse } from 'axios';
import { BACKEND_ERROR_CODE, createFlatRequest, createRequest } from '@sa/axios';
import { useAuthStore } from '@/store/modules/auth';
import { localStg } from '@/utils/storage';
import { getServiceBaseURL } from '@/utils/service';
import { $t } from '@/locales';
import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared';
import type { RequestInstanceState } from './type';

/** Extract response code and message from various response formats */
function extractResponseInfo(responseData: any) {
  let responseCode = '';
  let errorMsg = '';

  if (responseData.code !== undefined && responseData.msg !== undefined) {
    // 格式1: { code: 200, msg: "success", data: {...} } - 你的后端Result格式
    responseCode = String(responseData.code);
    errorMsg = responseData.msg || '';
  } else if (responseData.status !== undefined) {
    // 格式2: { status: "200", message: "success", result: {...} }
    responseCode = String(responseData.status);
    errorMsg = responseData.message || '';
  } else if (responseData.success !== undefined) {
    // 格式4: { success: true, code: 200, message: "success", data: {...} } - 你的后端格式
    responseCode = String(responseData.code || (responseData.success ? 200 : 500));
    errorMsg = responseData.message || '';
  } else {
    responseCode = '500';
    errorMsg = 'Unknown error';
  }

  return { responseCode, errorMsg };
}

/** Extract error message and code from error response */
function extractErrorInfo(error: any) {
  let message = error.message;
  let backendErrorCode = '';

  if (error.code === BACKEND_ERROR_CODE) {
    const responseData = error.response?.data as any;

    if (responseData?.msg !== undefined) {
      // 格式1: { code: 200, msg: "success", data: {...} } - 你的后端Result格式
      message = responseData.msg;
      backendErrorCode = String(responseData.code || '');
    } else if (responseData?.message !== undefined) {
      // 格式2: { status: "200", message: "success", result: {...} }
      message = responseData.message;
      backendErrorCode = String(responseData.status || '');
    } else if (responseData?.success !== undefined) {
      // 格式4: { success: true, code: 200, message: "success", data: {...} } - 你的后端格式
      message = responseData.message || 'Request failed';
      backendErrorCode = String(responseData.code || (responseData.success ? 200 : 500));
    } else {
      message = responseData?.message || error.message;
      backendErrorCode = String(responseData?.code || responseData?.status || '');
    }
  }

  return { message, backendErrorCode };
}

const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
const { baseURL, otherBaseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);

export const request = createFlatRequest<App.Service.Response, RequestInstanceState>(
  {
    baseURL,
    headers: {
      apifoxToken: 'XL299LiMEDZ0H5h3A29PxwQXdMJqWyY2'
    }
  },
  {
    async onRequest(config) {
      const Authorization = getAuthorization();
      Object.assign(config.headers, { Authorization });

      return config;
    },
    isBackendSuccess(response) {
      // 适配多种后端响应格式
      const responseData = response.data as any;

      // 格式1: { code: 200, msg: "success", data: {...} } - 你的后端Result格式
      if (responseData.code !== undefined && responseData.msg !== undefined) {
        return responseData.code === 200 || responseData.code === '200';
      }

      // 格式2: { status: "200", message: "success", result: {...} }
      if (responseData.status !== undefined) {
        return String(responseData.status) === '200';
      }

      // 格式3: 直接返回数据，没有包装结构
      if (responseData.userId || responseData.userName) {
        return true;
      }

      // 格式4: { success: true, code: 200, message: "success", data: {...} }
      if (responseData.success !== undefined) {
        return responseData.success === true;
      }

      return false;
    },
    async onBackendFail(response, instance) {
      const authStore = useAuthStore();
      const { responseCode, errorMsg } = extractResponseInfo(response.data as any);

      function handleLogout() {
        authStore.resetStore();
      }

      function logoutAndCleanup() {
        handleLogout();
        window.removeEventListener('beforeunload', handleLogout);
        request.state.errMsgStack = request.state.errMsgStack.filter(msg => msg !== errorMsg);
      }

      // Handle logout codes
      const logoutCodes = import.meta.env.VITE_SERVICE_LOGOUT_CODES?.split(',') || [];
      if (logoutCodes.includes(responseCode)) {
        handleLogout();
        return null;
      }

      // Handle modal logout codes
      const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
      if (modalLogoutCodes.includes(responseCode) && !request.state.errMsgStack?.includes(errorMsg)) {
        request.state.errMsgStack = [...(request.state.errMsgStack || []), errorMsg];
        window.addEventListener('beforeunload', handleLogout);

        window.$dialog?.error({
          title: $t('common.error'),
          content: errorMsg,
          positiveText: $t('common.confirm'),
          maskClosable: false,
          closeOnEsc: false,
          onPositiveClick: logoutAndCleanup,
          onClose: logoutAndCleanup
        });

        return null;
      }

      // Handle expired token codes
      const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
      if (expiredTokenCodes.includes(responseCode)) {
        const success = await handleExpiredRequest(request.state);
        if (success) {
          const Authorization = getAuthorization();
          Object.assign(response.config.headers, { Authorization });
          return instance.request(response.config) as Promise<AxiosResponse>;
        }
      }

      return null;
    },
        transformBackendResponse(response) {
      // 适配多种后端响应格式
      const responseData = response.data as any;

      // 格式1: { code: 200, msg: "success", data: {...} } - 你的后端Result格式
      if (responseData.data !== undefined) {
        return responseData.data;
      }

      // 格式2: { status: "200", message: "success", result: {...} }
      if (responseData.result !== undefined) {
        return responseData.result;
      }

      // 格式3: 直接返回数据，没有包装结构
      if (responseData.userId || responseData.userName) {
        return responseData;
      }

      // 格式4: { success: true, code: 200, message: "success", data: {...} } - 你的后端格式
      if (responseData.success !== undefined && responseData.data !== undefined) {
        return responseData.data;
      }

      // 默认返回整个响应数据
      return responseData;
    },
    onError(error) {
      const { message, backendErrorCode } = extractErrorInfo(error);

      // the error message is displayed in the modal
      const modalLogoutCodes = import.meta.env.VITE_SERVICE_MODAL_LOGOUT_CODES?.split(',') || [];
      if (modalLogoutCodes.includes(backendErrorCode)) {
        return;
      }

      // when the token is expired, refresh token and retry request, so no need to show error message
      const expiredTokenCodes = import.meta.env.VITE_SERVICE_EXPIRED_TOKEN_CODES?.split(',') || [];
      if (expiredTokenCodes.includes(backendErrorCode)) {
        return;
      }

      showErrorMsg(request.state, message);
    }
  }
);

export const demoRequest = createRequest<App.Service.DemoResponse>(
  {
    baseURL: otherBaseURL.demo
  },
  {
    async onRequest(config) {
      const { headers } = config;

      // set token
      const token = localStg.get('token');
      const Authorization = token ? `Bearer ${token}` : null;
      Object.assign(headers, { Authorization });

      return config;
    },
    isBackendSuccess(response) {
      // when the backend response code is "200", it means the request is success
      // you can change this logic by yourself
      return response.data.status === '200';
    },
    async onBackendFail(_response) {
      // when the backend response code is not "200", it means the request is fail
      // for example: the token is expired, refresh token and retry request
    },
    transformBackendResponse(response) {
      return response.data.result;
    },
    onError(error) {
      // when the request is fail, you can show error message

      let message = error.message;

      // show backend error message
      if (error.code === BACKEND_ERROR_CODE) {
        message = error.response?.data?.message || message;
      }

      window.$message?.error(message);
    }
  }
);
